package actions;


import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import matlab.IndexDir;
import cli.OmeroServer;
import cli.FileOperations;
import cli.Settings;
import omero.ServerError;
import pojos.ImageData;
import exception.DataException;
import exception.MatlabException;
import exception.ServerConnectionException;

/**
 * Create index files for the images identified <br/>
 * Indexing is done by the matlab routines and involves <br/>
 * creating a Description file (.des) and a .frm file <br/>
 * Index files are attached to the image and stored in the Omero database <br/>
 * If the image already has both des and frm files attached then this image will <br/>
 * not be indexed again but will be skipped
 * 
 * @author Peter
 */
public class Indexing implements Serializable {
	
	private static String tempImageDir;
	private static String tempIndexDir;
	
	/**
	 * Constructor
	 */
	public Indexing()  {
		
	}

	/**
	 * Index all images that are contained in the dataSet. <br/>
	 * Results are attached as .des and .frm attachments to the images
	 * @param dataSetId identifies the dataSet
	 * @throws NoSuchAlgorithmException
	 * @throws ServerError
	 * @throws IOException
	 * @throws DataException 
	 */
	public static void start( long dataSetId)  
		throws ServerError, IOException, NoSuchAlgorithmException, DataException, MatlabException {
		
		perform( dataSetId );
		
	}
	
	/**
	 * perform indexing, assuming that connecting is established
	 * 
	 * @param dataSetId
	 * @throws ServerError
	 * @throws IOException
	 * @throws NoSuchAlgorithmException 
	 * @throws DataException 
	 * @throws Exception
	 */
	public static void perform( long dataSetId ) 
			throws ServerError, IOException, NoSuchAlgorithmException, DataException, MatlabException  {

		tempImageDir = Settings.getTempImageDir();
		tempIndexDir = Settings.getTempIndexDir();
		
		if ( OmeroServer.getImagesInDataSet(dataSetId) == null ) {
			throw new DataException( "Dataset Id "+ dataSetId  + " is invalid");
		}
			
		//clean up temp directories
		System.out.println( "Cleaning up temp dirs...");
		FileOperations.deleteFilesInDir(new File( tempImageDir ) );
		FileOperations.deleteFilesInDir(new File( tempIndexDir ) );
		
		//get list of images in the dataset
		Set<ImageData> images = OmeroServer.getImagesInDataSet( dataSetId );
		
		Set<ImageData> indexingImages = new HashSet<ImageData>();
		
		Iterator<ImageData> j = images.iterator();
		ImageData image;

		//for each image in the dataset
		while ( j.hasNext() ) {
			image = j.next();
			
			//check if image has already .des and .frm attached
			System.out.print( "id " + image.getId() + " - " + image.getName() + " - " );
			if ( OmeroServer.getIndexAttachments( image ) == null ) {
				System.out.println( "Requeres indexing..." );
				//add to the list of images that need indexing
				indexingImages.add( image ); 
				//get image pixels and store in temp directory
				BufferedImage bufImg = OmeroServer.renderImage(image.getId() );
				String fullFilename = Settings.getTempImageDir() + "/" + image.getName();
				FileOperations.saveFileAsTIFF(fullFilename, bufImg );	
			} else {
				System.out.println( " already indexed" );
			}
		}
		
		//all images that need to be indexed are now in the temp directory
		//if the directory is empty then nothing needs to be  indexed
		
		//all images in the temp dir will now be indexed and the results will be placed in 
		//index temp dir
				
		//
		//calling matlab to do the indexing
		if ( indexingImages.size()  < 1 ) {
			System.out.println( "Matlab indexing not required" );
			return;
		} 
		
		System.out.println( "Matlab indexing for " + indexingImages.size() + " images started" );		
		IndexDir.createIndex( tempImageDir + "/", tempIndexDir+"/" );
		System.out.println( "Matlab indexing finished" );

		//
		//
		
		//results of indexing is in temp dir
		//attach results of indexing (.des and .frm) files to images in omero server
		//for each of the images find the des and frm files in the temp dir
		Iterator<ImageData> k = indexingImages.iterator();
		ImageData indexImage;
		
		System.out.println( "Uploading index files for " + indexingImages.size() + " images into Omero" );
		while ( k.hasNext() ) {				
			indexImage = k.next();			
			String imageFullName = indexImage.getName();
			String imageBodyName = FileOperations.filenameBody( imageFullName );
			String imageDesFilename = tempIndexDir + "/" + imageBodyName + ".des";
			String imageFrmFilename = tempIndexDir + "/" + imageBodyName + ".frm";
			
			File desFile = new File( imageDesFilename );
			File frmFile = new File( imageFrmFilename );
			//ensure both files exist
			if ( desFile.exists() && frmFile.exists() ) {
				// attach des file
				String generatedSha1 = FileOperations.generateSha1( imageDesFilename );
				OmeroServer.addFileToImage( imageDesFilename, generatedSha1, indexImage, "index" );
				// attach frm file
				generatedSha1 = FileOperations.generateSha1( imageFrmFilename );
				OmeroServer.addFileToImage( imageFrmFilename, generatedSha1, indexImage, "index" );
				//System.out.println( "id " + indexImage.getId() + " - Index files for " + indexImage.getName() + " added to Omero" );					
			} else {
				System.out.println( "id " + indexImage.getId() + " - index files for " + indexImage.getName() + " NOT found" );
			}
		}
		System.out.println( "Uploading indexed files into Omero finished" );
	}

}
